package lib

import (
	"context"
	"errors"
	"fmt"
	"log"
	"strings"
	"time"

	clientv3 "go.etcd.io/etcd/client/v3"
	"go.etcd.io/etcd/client/v3/concurrency"
)

type EtcdRegistry struct {
	endpoint string
	client   *clientv3.Client
	// 租约
	sess *concurrency.Session
}

func NewEtcdRegistry(etcdHosts []string, timeout time.Duration) (*EtcdRegistry, error) {
	cli, err := NewEtcdClient(etcdHosts, timeout)
	if err != nil {
		log.Fatal("Error connecting to etcd:", err)
	}

	// etcd 内置租约，内部实现了创建租约、自动续期
	sess, err := concurrency.NewSession(cli, concurrency.WithTTL(10))
	if err != nil {
		return nil, err
	}

	return &EtcdRegistry{
		client: cli,
		sess:   sess,
	}, nil
}

// 具体服务端向 etcd 上报，
// serverInfo 是 ip:port,weight 格式，
// 为了简化处理，需要自己提供 etcd 连接参数
func (r *EtcdRegistry) Register(endpoint, info string) error {
	if !strings.Contains(info, ":") || !strings.Contains(info, ",") {
		return errors.New(`Error info format, for example "ip:port,weight"`)
	}
	r.endpoint = endpoint

	_, err := r.client.Put(context.Background(), instanceKey(endpoint), info, clientv3.WithLease(r.sess.Lease()))
	return err
}

func (r *EtcdRegistry) Unregister(ctx context.Context, endpoint string) error {
	if endpoint == "" {
		endpoint = r.endpoint
	}
	_, err := r.client.Delete(ctx, instanceKey(endpoint))
	return err
}

func (r *EtcdRegistry) Close() error {
	err := r.sess.Close()
	if err != nil {
		fmt.Println("sess close")
		return err
	}
	return r.client.Close()
}
